package rps.client;

import static rps.network.NetworkUtil.hostNetworkGame;

import java.rmi.RemoteException;

import rps.client.ui.GamePane;
import rps.game.Game;
import rps.game.data.FigureKind;
import rps.game.data.Player;
import rps.network.GameRegistry;
import rps.network.NetworkUtil;

/**
 * this class is responsible for controlling all game related events.
 */
public class GameController implements GameListener {

	private UIController uiController;
	private GamePane gamePane;
	private FigureKind assignment;
	private GameRegistry registry;
	private Player player;
	private Game game;

	public void setComponents(UIController uiController, GamePane gamePane) {
		this.uiController = uiController;
		this.gamePane = gamePane;
	}

	public void startHostedGame(Player player, String host) {
		this.player = player;
		registry = hostNetworkGame(host);
		register(player, this);
	}

	public void startJoinedGame(Player player, String host) {
		this.player = player;
		registry = NetworkUtil.requestRegistry(host);
		register(player, this);
	}

	public void startAIGame(Player player, GameListener ai) {
		this.player = player;
		registry = NetworkUtil.hostLocalGame();
		register(new Player(ai.toString()), ai);
		register(player, this);
	}

	private void register(Player player, GameListener listener) {
		try {
			GameListener multiThreadedListener = decorateListener(listener);
			registry.register(multiThreadedListener);
		} catch (RemoteException e) {
			throw new RuntimeException(e);
		}
	}

	private static GameListener decorateListener(GameListener listener) {
		try {
			listener = new MultiThreadedGameListener(listener);
			listener = new RMIGameListener(listener);
			return listener;
		} catch (RemoteException e) {
			throw new RuntimeException(e);
		}
	}

	public void unregister() {
		try {
			if (registry != null) {
				registry.unregister(player);
			}
		} catch (RemoteException e) {
			throw new RuntimeException(e);
		}
	}

	public void surrender() {
		try {
			game.surrender(player);
		} catch (RemoteException e) {
			throw new RuntimeException(e);
		}
	}

	public void resetForNewGame() {
		gamePane.reset();
	}

	public void exit() {
		if (registry != null) {
			unregister();
		}
		if (game != null) {
			surrender();
		}
	}

	@Override
	public void chatMessage(Player sender, String message) throws RemoteException {
		gamePane.receivedMessage(sender, message);
	}

	@Override
	public void provideInitialAssignment(Game game) throws RemoteException {
		this.game = game;
		uiController.switchToGamePane();
		gamePane.startGame(player, game);
	}

	@Override
	public void provideInitialChoice() throws RemoteException {
		gamePane.receivedMessage(player, "Startauswahl treffen");
		gamePane.askForChoice();
	}

	@Override
	public void startGame() throws RemoteException {
		gamePane.gameStarted();
		System.out.println("Spiel gestartet");
	}
	
	@Override
	public void provideNextMove() throws RemoteException {
	//	System.out.println("update");
		gamePane.lockScreen(false);
		gamePane.updateBoard();
		gamePane.showLastMove();
	}

	@Override
	public void figureMoved() throws RemoteException {
		gamePane.updateBoard();
		gamePane.showLastMove();
	}

	@Override
	public void figureAttacked() throws RemoteException {
		gamePane.updateBoard();
		gamePane.showLastMove();
	}

	@Override
	public void provideChoiceAfterFightIsDrawn() throws RemoteException {
		gamePane.updateBoard();
		gamePane.askForChoice();
	}

	@Override
	public void gameIsLost() throws RemoteException {
		game.sendMessage(player, "Jetzt nochmal ohne Schummeln, dann kannst Du's vergessen gegen mich zu gewinnen!");
		gamePane.popUpInfo("Spiel verloren!");
		gamePane.updateBoard();
	}

	@Override
	public void gameIsWon() throws RemoteException {
		gamePane.updateBoard();
		game.sendMessage(player, "Yipiyayeah motherfucker, abgezogen! Willst Du nochmal verlieren?");
		gamePane.popUpInfo("Spiel gewonnen!");
		startNewGame();
	}

	@Override
	public void gameIsDrawn() throws RemoteException {
		game.sendMessage(player, "Das ist ja fast schlimmer als zu verlieren. Los nochmal!");
		gamePane.popUpInfo("Unentschieden!");
		startNewGame();
	}

	public void startNewGame(){
		if (gamePane.popUpNewGame()){
				uiController.handleNewGame();
		} else{uiController.handleExit();}
	}
	
	
	
	@Override
	public Player getPlayer() throws RemoteException {
		return this.player;
	}
}